package com.bole.springboot_webflux.controller;

import com.bole.springboot_webflux.dao.UserRepository;
import com.bole.springboot_webflux.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

/**
 * HelloController - 用户管理 REST API 控制器
 * 提供标准的用户 CRUD 操作接口
 */
@RestController
@RequestMapping("/api")
public class HelloController {

    private static final Logger log = LoggerFactory.getLogger(HelloController.class);

    @Autowired
    private UserRepository userRepository;

    /**
     * 获取所有用户列表
     * @return 用户列表 Flux 流
     */
    @GetMapping("/users")
    public Flux<User> getAllUsers() {
        log.info("获取所有用户列表");
        return userRepository.findAll()
                .doOnNext(user -> log.debug("查询到用户: {}", user.getName()));
    }

    /**
     * 根据ID获取单个用户
     * @param id 用户ID
     * @return 用户信息 Mono 对象，如果用户不存在返回 404
     */
    @GetMapping("/users/{id}")
    public Mono<ResponseEntity<User>> getUserById(@PathVariable Long id) {
        log.info("根据ID查询用户: {}", id);
        return userRepository.findById(id)
                .map(user -> {
                    log.info("找到用户: {}", user.getName());
                    return ResponseEntity.ok(user);
                })
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    /**
     * 根据用户名查询用户
     * @param name 用户名
     * @return 用户信息 Mono 对象，如果用户不存在返回 404
     */
    @GetMapping("/users/search/by-name")
    public Mono<ResponseEntity<User>> getUserByName(@RequestParam String name) {
        log.info("根据用户名查询用户: {}", name);
        return userRepository.findByName(name)
                .map(user -> {
                    log.info("找到用户: {}", user.getName());
                    return ResponseEntity.ok(user);
                })
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    /**
     * 根据邮箱查询用户
     * @param email 邮箱地址
     * @return 用户信息 Mono 对象，如果用户不存在返回 404
     */
    @GetMapping("/users/search/by-email")
    public Mono<ResponseEntity<User>> getUserByEmail(@RequestParam String email) {
        log.info("根据邮箱查询用户: {}", email);
        return userRepository.findByEmail(email)
                .map(user -> {
                    log.info("找到用户: {}", user.getName());
                    return ResponseEntity.ok(user);
                })
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    /**
     * 创建新用户
     * @param user 用户信息
     * @return 创建的用户信息 Mono 对象
     */
    @PostMapping("/users")
    public Mono<ResponseEntity<User>> createUser(@RequestBody User user) {
        log.info("创建新用户 - 用户名: {}, 邮箱: {}", user.getName(), user.getEmail());
        
        return userRepository.existsByName(user.getName())
                .flatMap(nameExists -> {
                    if (nameExists) {
                        log.warn("用户名已存在: {}", user.getName());
                        return Mono.just(ResponseEntity.status(HttpStatus.CONFLICT).build());
                    }
                    
                    return userRepository.existsByEmail(user.getEmail())
                            .flatMap(emailExists -> {
                                if (emailExists) {
                                    log.warn("邮箱已存在: {}", user.getEmail());
                                    return Mono.just(ResponseEntity.status(HttpStatus.CONFLICT).build());
                                }
                                
                                // 设置创建时间和更新时间
                                user.setCreatedAt(LocalDateTime.now());
                                user.setUpdatedAt(LocalDateTime.now());
                                
                                return userRepository.save(user)
                                        .map(savedUser -> {
                                            log.info("用户创建成功: {}", savedUser.getName());
                                            return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
                                        });
                            });
                });
    }

    /**
     * 更新用户信息
     * @param id 用户ID
     * @param user 更新的用户信息
     * @return 更新后的用户信息 Mono 对象，如果用户不存在返回 404
     */
    @PutMapping("/users/{id}")
    public Mono<ResponseEntity<User>> updateUser(@PathVariable Long id, @RequestBody User user) {
        log.info("更新用户信息 - ID: {}", id);
        
        return userRepository.findById(id)
                .flatMap(existingUser -> {
                    log.info("找到要更新的用户: {}", existingUser.getName());
                    
                    // 更新用户信息
                    if (user.getName() != null) {
                        existingUser.setName(user.getName());
                    }
                    if (user.getEmail() != null) {
                        existingUser.setEmail(user.getEmail());
                    }
                    existingUser.setUpdatedAt(LocalDateTime.now());
                    
                    return userRepository.save(existingUser)
                            .map(updatedUser -> {
                                log.info("用户更新成功: {}", updatedUser.getName());
                                return ResponseEntity.ok(updatedUser);
                            });
                })
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    /**
     * 删除用户
     * @param id 用户ID
     * @return 删除操作结果 Mono 对象
     */
    @DeleteMapping("/users/{id}")
    public Mono<ResponseEntity<Void>> deleteUser(@PathVariable Long id) {
        log.info("删除用户 - ID: {}", id);
        
        return userRepository.findById(id)
                .flatMap(user -> {
                    log.info("删除用户: {}", user.getName());
                    return userRepository.delete(user)
                            .then(Mono.just(ResponseEntity.ok().<Void>build()));
                })
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    // 保留原有的示例方法，但移除阻塞代码
    @GetMapping("/hello")
    public String hello() {
        log.info("开始时间：" + System.currentTimeMillis());
        String result = createStr();
        log.info("结束时间：" + System.currentTimeMillis());
        return result;
    }

    @GetMapping("/mono")
    public Mono<String> mono() {
        log.info("开始时间：" + System.currentTimeMillis());
        Mono<String> result = Mono.fromSupplier(this::createStr);
        log.info("结束时间：" + System.currentTimeMillis());
        return result;
    }

    @GetMapping(value = "/flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> flux() {
        log.info("生成 Flux 数据流");
        return Flux.just("flux data--1", "flux data--2", "flux data--3", "flux data--4")
                .doOnNext(data -> log.debug("发送数据: {}", data));
    }

    /**
     * 创建字符串（移除阻塞代码）
     * @return 字符串结果
     */
    private String createStr() {
        log.info("创建字符串");
        return "hello world";
    }
}

